using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using OWED.Network;
using OWED.Network.Messages;
using OWED.Network.Messages.General;
using OWED.Network.Messages.Reply;

using System.Threading;

using System.Timers;

using ClientGUI.Widgets;

namespace ClientGUI.Main.PopUpWindows
{
    public partial class LoginForm : NetworkDialog
    {
        MainForm my_parent;
        int my_width;
        int my_height;

        /// <summary>
        /// ... constructor ...
        /// </summary>
        /// <param name="main"></param>
        public LoginForm(MainForm main): base("Login:", main)
        {
            InitializeComponent();
            my_parent = main;
            my_width = 285;
            my_height = 367;
            Width = 285;
            Height = 367;

            serv_addr_entry.Text = "localhost";
            port_entry.Text = "1771";
        }

        

        private void Login_Load(object sender, EventArgs e)
        {
            server_panel.Hide();
            my_height = Height - server_panel.Height;
            Height -= server_panel.Height;


            uname_entry.Focus();
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void login_btn_Click(object sender, EventArgs e)
        {
            login_btn.Enabled = false;
            int port;

            if (uname_entry.Text.Length == 0)
            {
                StatusMessage("User name is required");
                login_btn.Enabled = true;
                return;
            }
            if (pass_entry.Text.Length == 0)
            {
                StatusMessage("Password is required");
                login_btn.Enabled = true;
                return;
            }
            if (serv_addr_entry.Text.Length == 0)
            {
                StatusMessage("Server address must be filled in");
                login_btn.Enabled = true;
                return;
            }
            if (port_entry.Text.Length == 0)
            {
                StatusMessage( "I need a port to connect to");
                login_btn.Enabled = true;
                return;
            }
            else if(!int.TryParse(port_entry.Text, out port))
            {
                StatusMessage("Port must be an integer");
                login_btn.Enabled = true;
                return;
            }

            String uname = uname_entry.Text;
            String server = serv_addr_entry.Text;
            String pass = pass_entry.Text;
            bool done = false;
            bool status_change = false;
            String status = "Something odd went wrong!";
            object _lock = new object();
            PassFail reply = null;
            Connection conn = null;

            //Otherwise we can proceed to login!
            StatusMessage( "Connecting...");


            /*
             * This method is called in a second thread and does the login stuffs.
             * It also keeps status up to date so that the user can see what's happening.
             */
            ThreadStart login_thr = delegate()
            {
                try
                {
                    conn = new Connection(server, port, 
                        my_parent.ConnectionExceptionHandle);
                }
                catch (ConnectionException exc)
                {
                    lock (_lock)
                    {
                        status_change = true;
                        status = exc.Message;
                        done = true;
                        return;
                    }
                }

                lock (_lock)
                {
                    status_change = true;
                    status = "Connected, logging on...";
                }
            
                Login request = new Login(new User(uname), new Password(pass));

                reply = null;
                try
                {
                    reply = MessageGet.GetFromXml
                        (conn.Send(request.ToXml())) as PassFail;
                }
                catch (ConnectionException exc)
                {
                    lock (_lock)
                    {
                        status = exc.Message;
                        status_change = true;
                        done = true;
                        return;
                    }
                }
                done = true;
            };

            Thread t1 = new Thread(login_thr);
            t1.IsBackground = true;
            t1.Start();

            /*
             * We're going to spinwait and update the statusbar.
             */
            while (!done)
            {
                this.Refresh();
                Thread.Sleep(30);
                lock (_lock)
                {
                    if (status_change)
                    {
                        StatusMessage( status);
                        status_change = false;
                    }
                }
            }


            if (reply == null)
            {
                StatusMessage("Failed for unknown reason");
            }
            else if (reply.pass)
            {
                StatusMessage("You are logged in");
                my_parent.ProgramData.Connection = conn;
                my_parent.ProgramData.User = new User(uname);
                my_parent.Connected = true;
                for (int i = 0; i < 10; ++i)
                {
                    this.Refresh();
                    Thread.Sleep(40);
                } //wait for a second so they can see.
                Dispose(); //closing myself.
                login_btn.Enabled = true;
                return;
            }
            else
            {
                StatusMessage( reply.Reason.Value);
            }
            login_btn.Enabled = true;
            //failed:
            if (conn != null)
                conn.Dispose();
        }

        private void cancel_btn_Click(object sender, EventArgs e)
        {
            Dispose();
        }

        private void server_lnk_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (server_panel.Visible)
            {
                server_panel.Hide();
                my_height = Height - server_panel.Height;
                Height -= server_panel.Height;
            }
            else
            {
                server_panel.Show();
                my_height = Height + server_panel.Height;
                Height += server_panel.Height;
                serv_addr_entry.Focus();
            }
        }

        /// <summary>
        /// Keeps the window from being resized.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void LoginForm_Resize(object sender, EventArgs e)
        {
            Height = my_height;
            Width = my_width;
        }
    }
}